#include "Invokable.h"

#include "MethodInvoker.h"
#include "InvocationList.h"

namespace xgu{

Invokable::Invokable() : tid_(Thread::getTid())
{
	InvocationList::Register(*this);
}

Invokable::~Invokable()
{
	if (Thread::getTid() != tid_)
	{
		assert(!"Instance created in another thread is destructing!");
	}
	while (!mi_list_.empty())
	{
		MethodInvoker* mi = mi_list_.back();
		mi->Dispose();
		mi_list_.pop_back();
	}

	InvocationList::Unregister(*this);
}

void Invokable::BeginInvoke( const Delegate<void>& delegate, IAsyncResult** out_async_result )
{
	if (InvokeRequired())
	{
		MethodInvoker* mi = new MethodInvoker(*this, delegate, out_async_result);
		AutoLock autolock(milist_lock_);
		mi_list_.push_back(mi);
	}
	else
	{
		assert(out_async_result == NULL);
		delegate();
	}
}

void Invokable::Remove( MethodInvoker& mi )
{
	AutoLock autolock(milist_lock_);
	for (deque<MethodInvoker*>::iterator iter = mi_list_.begin();
		iter != mi_list_.end(); ++iter)
	{
		if (*iter == &mi)
		{
			mi_list_.erase(iter);
			return;
		}
	}
}

void Invokable::DoInvocations()
{
	AutoLock autolock(milist_lock_);
	while (mi_list_.size() > 0)
	{
		MethodInvoker* mi = mi_list_.front();
		assert(mi != NULL);

		mi_list_.pop_front();
		mi->Invoke();
	}
}

void Invokable::DoEvents()
{
	InvocationList::DoEvents();
}

}
